package cn.xo68.boot.job.jdbcstore.lock.impl;

import cn.xo68.boot.job.entity.DistributedLock;
import cn.xo68.boot.job.entity.DistributedLockStatus;
import cn.xo68.boot.job.jdbcstore.lock.DistributedLockStore;
import cn.xo68.core.jdbc.JdbcOperate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class DistributedLockStoreImpl implements DistributedLockStore {

    private static final Logger logger=LoggerFactory.getLogger(DistributedLockStoreImpl.class);

    private static final String insert_sql="insert into wx_job_lock ( lock_key , create_time , lock_status , lock_hold , lock_expire ) values ( ? , ? , ? , ? , ? )";
    private static final String get_sql="select t.* from wx_job_lock t where t.lock_key=?";
    private static final String delete_sql="delete from wx_job_lock  where lock_key=?";
    private static final String delete_Expire_Sql="delete from wx_job_lock where lock_key=? and lock_expire < ?";

    private final JdbcOperate jdbcOperate;

    public DistributedLockStoreImpl(JdbcOperate jdbcOperate) {
        this.jdbcOperate = jdbcOperate;
    }



    @Transactional("jobTransactionManager")
    @Override
    public DistributedLock tryLock(String lockKey, String lockHold, long timeout) {
        Date current=new Date();
        Date expireDate=new Date(current.getTime() + timeout);

        DistributedLock lock=new DistributedLock();
        lock.setLockKey(lockKey);
        lock.setLockHold(lockHold);
        lock.setCreateTime(current);
        lock.setLockExpire(expireDate);
        lock.setLockStatus(DistributedLockStatus.R.name());


        List<Object> deleteArgList=new ArrayList<>();
        deleteArgList.add(lock.getLockKey());
        deleteArgList.add(current);
        jdbcOperate.update(delete_Expire_Sql, deleteArgList.toArray());

        List<Object> insertArgList=new ArrayList<>();
        insertArgList.add(lock.getLockKey());
        insertArgList.add(lock.getCreateTime());
        insertArgList.add(lock.getLockStatus());
        insertArgList.add(lock.getLockHold());
        insertArgList.add(lock.getLockExpire());

        int effectRow=jdbcOperate.update(insert_sql, insertArgList.toArray());
        if(effectRow < 1){
            return null;
        }
        return lock;
    }

    @Override
    public void unLock(String lockKey) {
        List<Object> insertArgList=new ArrayList<>();
        insertArgList.add(lockKey);
        int effectRow= jdbcOperate.update(delete_sql, insertArgList.toArray());
    }
}
